#ifndef G3_JPEG_H
#define G3_JPEG_H

#include "log.h"
#include "file/f_stream.h"
#include "tex_bitmap.h"

extern "C" {
	#include <jpeglib.h>
	#include <jerror.h>
}

#ifndef SETJMP_H
	#include <setjmp.h>
#endif

#define JPG_BUFFER_SIZE		4096

namespace G3 {

struct JPG_ERROR_MANAGER: public jpeg_error_mgr {
	JPG_ERROR_MANAGER ();

	// for return to caller
	jmp_buf setjmp_buffer;
	// for error logging
	LOG *log;
};

typedef struct JPG_ERROR_MANAGER *JPG_ERROR_POINTER;

struct JPG_SOURCE_MANAGER {
	// "public" fields
	struct jpeg_source_mgr pub;

	STREAM *stream;

	bool file_started;

	JOCTET buffer [JPG_BUFFER_SIZE];
};

typedef JPG_SOURCE_MANAGER * JPG_SOURCE_POINTER;

//==============================================================================
// Ment to replace the standard error_exit method. Instead of the standard method,
// this one does not exit. It returns to the last jumppoint set.
//
//	A jumppoint can be set like this:
//
//	JPG_ERROR_MANAGER jerm;
//	int retval = setjmp (jerm.setjmp_buffer);
//	// We land here (retval = 1) if a fatal error ocurrs
//	if (retval == 1)
//		return NULL;
//
//	USAGE:: struct jpeg_decompress_struct::err->error_exit = G3::jpg_error_exit
//
//	NOTE:: In order to redirect error messages to a log, JPG_ERROR_MANAGER::log
//		   should be set to point to an existing G3::LOG class
//==============================================================================
void/*METHODDEF(void)*/ jpg_error_exit (j_common_ptr cinfo);

//==============================================================================
// This is used to override libJPEG default output_message.
//
//	When JPG_ERROR_MANAGER::log is set properly and the error manager is loaded
//	like this:
//
//	JPG_ERROR_MANAGER jerm;
//	struct jpeg_decompress_struct cinfo;
//	cinfo.err = jpeg_std_error (&jerm);
//
//	Then error messages are reported into the log instead of just stderr
//==============================================================================
void/*METHODDEF(void)*/ jpg_output_message (j_common_ptr cinfo);

//==============================================================================
// Initializes a stream source for libJPEG
//==============================================================================
void/*METHODDEF(void)*/ init_source (j_decompress_ptr cinfo);

//==============================================================================
// Fills libJPEG input buffer
//==============================================================================
boolean/*METHODDEF(boolean)*/ fill_input_buffer (j_decompress_ptr cinfo);

//==============================================================================
// Skips num_bytes from the input stream source
//==============================================================================
void/*METHODDEF(void)*/ skip_input_data (j_decompress_ptr cinfo, long num_bytes);

//==============================================================================
// Terminates the libJPEG stream source
//==============================================================================
void/*METHODDEF(void)*/ term_source (j_decompress_ptr cinfo);

//==============================================================================
// Allows us to specify a filestream as a libJPEG source
//==============================================================================
GLOBAL(void) jpeg_stream_src (j_decompress_ptr cinfo, STREAM *stream);

//==============================================================================
// Loads a JPG file from the Stream
//
//		FILESTREAM *Stream			Stream where to read the jpg file from
//
//		LOG *Log					Pointer to the log file where we report errors to
//
//	Returns a pointer to the loaded bitmap on success. Returns NULL on failure..
//==============================================================================
boost::shared_ptr<G3::BITMAP> LoadJPG (STREAM *Stream, LOG *Log);

//bool SaveJPG (BITMAP *Bitmap, FILESTREAM *Stream, LOG *Log);

}

#endif
